package fr.gmdev.mail.fonction.mail;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

public class MailMessage {

	private MimeMessage message ;
	
	private String corps ;
	private List<PieceJointe> piecesJointes = new ArrayList<PieceJointe>();

	public MailMessage(MimeMessage message) {
		super();
		this.message = message;
	}
	
	public Address[] getTo(){
		try {
			return message.getRecipients(RecipientType.TO);
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}
	
	public Address[] getCC(){
		try {
			return message.getRecipients(RecipientType.CC);
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}
	
	public Address[] getBCC(){
		try {
			return message.getRecipients(RecipientType.BCC);
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}

	public Address[] getAllReciepints(){
		try {
			return message.getAllRecipients();
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}
	
	public Address[] getFrom(){
		try {
			return message.getFrom();
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}
	
	public Address[] geReplyTo(){
		try {
			return message.getReplyTo();
		} catch (MessagingException e) {
			e.printStackTrace();
			return null ;
		}
	}
	

	public void parse() throws IOException, MessagingException{
		dump (message);
	}
	
    public void dump(Object o) throws IOException, MessagingException {
        if (o instanceof Part) {
            Part p= (Part) o;
            if (!parsingAttachement(p,true))
            {
                try {
                    patchIgnorePGP(p);
                    o = p.getContent();
                }
                catch (UnsupportedEncodingException uex) {
                   // Si on reconnais pas le charset on supprime du header pour essayer tout de même de lire le mail
                    PieceJointe.patchEncodingProblem(p);
                    o = p.getContent();
                }
            }
            else
            {
                return; // La pièce a été parsé on quitte.
            }
        }
       if (o instanceof Multipart) {
            Multipart mp = (Multipart) o;
            int count = mp.getCount();
            for (int i = 0; i < count; i++) {
                dump(mp.getBodyPart(i));
            }
        }
        else if (o instanceof Message) {
            dump(o);
        }
        else if (o instanceof String)
        {
            setCorps(((String)o));
        }
    }

    
    public boolean parsingAttachement(Part p, boolean essaiConversionUSASCI) throws MessagingException, IOException
    {
        boolean isAttachement = false;
        boolean isToForceDump = false;

                String dispo = p.getDisposition();
                if ( (dispo != null) &&
                    ( (dispo.equalsIgnoreCase(Part.ATTACHMENT)) || (dispo.equalsIgnoreCase(Part.INLINE))) &&
                    p.getFileName() != null) {
                    dumpAttachement(p);
                    isAttachement = true;
                }

        return isAttachement;

    }

    public void dumpAttachement(Part p) throws MessagingException, IOException {
        String contentType = p.getContentType();
        Exception exNotif = null;
        boolean signature = (contentType != null) &&
            (contentType.startsWith("application/x-pkcs7-signature") ||
             contentType.startsWith("application/x-pkcs7-mime") ||
             contentType.startsWith("application/x-pkcs10") ||
             contentType.startsWith("application/pkcs7-signature") ||
             contentType.startsWith("application/pkcs7-mime") ||
             contentType.startsWith("application/pkcs10"));
        try {
            piecesJointes.add(PieceJointe.getInstance(p, true));
        }
        catch (IOException ex) {
            if (signature) {
                exNotif = ex;
            }
            else {
                throw ex;
            }
        }
        catch (MessagingException ex) {
            if (signature) {
                exNotif = ex;
            }
            else {
                throw ex;
            }
        }
    }


    /**
     * Patch permettant d'ignorer la signature PGP, on la considère comme une pièce
     * jointe.
     * @param p Part
     * @throws MessagingException
     */
    private void patchIgnorePGP(Part p) throws MessagingException {
        String contentType = p.getContentType();
        if (contentType!=null&&contentType.indexOf("application/pgp-signature")!=-1&&
            contentType.indexOf("multipart/signed")!=-1){
            ArrayList parametre = decouper(contentType);
            String s3 = chercher(parametre,"boundary");
            if (s3!=null){
                p.setHeader("Content-Type","multipart/mixed; "+s3);
            }
        }
    }
    private ArrayList decouper(String chaine){
        ArrayList retour = new ArrayList();
        if (chaine!=null){
            StringTokenizer tokenizer = new StringTokenizer(chaine,";",false);
            while (tokenizer.hasMoreTokens()){
                retour.add(tokenizer.nextToken());
            }
        }
        return retour;
    }

    /**
     * Recherche dans les chaines passé en paramètre la chaine s
     * @param chaines String[]
     * @param s String
     * @return int
     */
    private String chercher(ArrayList chaines, String s){
        String retour = null;
        String chaine;
        for (int i=0;i<chaines.size();i++){
            chaine=(String)chaines.get(i);
            if (chaine!=null&&chaine.toLowerCase().indexOf(s)!=-1){
                retour = chaine;
                break;
            }
        }
        return retour;
    }

	public String getCorps() {
		return corps;
	}

	public void setCorps(String corps) {
		this.corps = corps;
	}

	public List<PieceJointe> getPiecesJointes() {
		return piecesJointes;
	}

	public void setPiecesJointes(List<PieceJointe> piecesJointes) {
		this.piecesJointes = piecesJointes;
	}
	

    public static void main(String[] args) throws Exception {
		FileInputStream fis = null ;
		
		try {
			
			
			fis = new FileInputStream("/home/gilbert/Téléchargements/test_dft.eml");
			MimeMessage mm = new MimeMessage(null, fis);
			
			MailMessage mail = new MailMessage(mm);
			mail.parse();
			System.out.println("corps:" + mail.getCorps());
			
			List<PieceJointe> piecesJointes = mail.getPiecesJointes();
			
			for (PieceJointe pieceJointe : piecesJointes) {
				System.out.println("pj trouvé nom:" + pieceJointe.getFilename() + " type:" + pieceJointe.getContentType() + " taille:" + pieceJointe.getContenu().length);
			}
			
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			fis.close();
		}
	}

	public MimeMessage getMessage() {
		return message;
	}

	public void setMessage(MimeMessage message) {
		this.message = message;
	}


}
